/**
 * @file BIAS.C
 * @brief 
 * @author xuesong (wenshaoliu@foxmail.com)
 * @version 1.0
 * @date 2023-11-17
 * 
 * @copyright Copyright (c) 2023  by xuesong
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2023-11-17     <td>1.0     <td>xuesong   <td>内容
 * </table>
 */
#include "CaculateBodyComp.h"
#include "string.h"
#include "stdio.h"

//-----------------------------------------------
#define MI_LOG_INFO(...)                        printf( __VA_ARGS__)
uint16_t Caculate2Persent(uint16_t Total,uint16_t part);
//-----------------------------------------------
UserInfor_t     userInfor;
UserCompostion_t userFinishData;
ScaleWeight_t   ScaleWeightInfor;
//-----------------------------------------------
/**
 * @brief 
 * @param  pdata   xor check soure
 * @param  len     source len
 * @return uint8_t check sum
 */
uint8_t buff_xorCheck(const uint8_t *pdata,uint8_t len)
{
   uint8_t CheckSum = 0;
   for(uint8_t i=0;i<len;i++)
   {
       CheckSum ^= *pdata;
       pdata++;
   }
    return CheckSum;
}
/**
 * @brief 
 * @param  weight           0.1kg
 * @param  standWeight      0.1kg
 * @return int16_t          0.1%
 */
int16_t CaculateFatLevle(uint16_t weight,uint16_t standWeight)
{
    int32_t subWeight = weight - standWeight;
    subWeight *=1000;
    subWeight /= standWeight;
    return subWeight&0xFFFF;
}
//-------------------------------------------------------------------------
/**
 * @brief 
 * @param  value            MyParamDoc
 * @param  levle            MyParamDoc
 * @param  ScoreArry        MyParamDoc
 * @param  maxIndex         MyParamDoc
 * @return int8_t           value > 0 positive pate
 */
static int8_t CaculateScore(uint16_t value,const uint16_t *levle,const uint16_t *ScoreArry,uint8_t maxIndex)
{
    uint8_t index = 0;
    bool    Negtive = false;
    for(index = 0;index < maxIndex;index++)
    {
        if(levle[index] > value)
            break;
    }
    int16_t Score = 0;
    if(index == 0)
    {
        Negtive = true;
        Score = (levle[0] - value)*(ScoreArry[1] - ScoreArry[0])/(levle[1] - levle[0]);
        Score = ScoreArry[0] - Score;
    }else{
        if(index >= maxIndex)
        {
            Score = (value - levle[maxIndex - 1])*(ScoreArry[maxIndex - 2] - ScoreArry[maxIndex - 1])/(levle[maxIndex - 1] - levle[maxIndex - 2]);
            Score = ScoreArry[maxIndex - 1] - Score;
        }else{
            Score = ScoreArry[index] - ScoreArry[index - 1];
            if(Score < 0)   
            {
                Score = 0 - Score;
                Score = Score *(levle[index] - value)/(levle[index] - levle[index - 1]);
                Score = ScoreArry[index] + Score;
            }else{
                Score = Score *(levle[index] - value)/(levle[index] - levle[index - 1]);
                Score = ScoreArry[index] - Score;  
                Negtive = true;
            }       
        }
    }
    if(Score < 0)
        Score = 0;
    if(Negtive)
        Score = 0 - Score;
    return Score&0xFF;
}
/**
 * @brief 
 * @param  Bmi    0.1 
 * @return uint8_t 
 */
int8_t CaculateBmiScore(uint16_t Bmi)
{
const uint16_t bmiLevle[10] = {150,  170,    190,    210,    215,    220,    240,    260,    280,    300};
const uint16_t bmiScore[10] = {40,   60,     70,     95,     100,    85,     70,     60,     50,     40};
// const uint16_t bmiScore[10] = {20,    40,     70,     95,     100,     85,     70,     60,     40,     20};
    uint8_t Score = CaculateScore(Bmi,bmiLevle,bmiScore,sizeof(bmiLevle)/sizeof(uint16_t));
    return Score;
}

int8_t CaculateFatScore(uint16_t fatRate,uint8_t sex,uint8_t age)
{
const uint16_t MaleAgeBelow39fat[10]    = {50,  75,     100,    130,    160,    185,    210,    240,    260,    280};
const uint16_t MaleAge40_59fat[10]      = {50,  80,     110,    140,    170,    195,    220,    245,    270,    285};
const uint16_t MaleAgeOver60fat[10]     = {50,  90,     130,    160,    190,    115,    240,    265,    290,    325};

const uint16_t FeMaleAgeBelow39fat[10]  = {50,  125,    200,    235,    270,    305,    340,    365,    390,    415};
const uint16_t FeMaleAge40_59fat[10]    = {50,  130,    210,    247,    280,    315,    350,    375,    400,    425};
const uint16_t FeMaleAgeOver60fat[10]   = {50,  135,    220,    255,    290,    325,    360,    285,    410,    435};

// const uint16_t FatScore[10]             = {20,  40,     70,     95,     100,    85,     70,     60,     40,     20};
const uint16_t FatScore[10]             = {40,   60,     70,     95,     100,    85,     70,     60,     50,     40};
int8_t Score;
    if(age < 40){
        if(sex == D_SEX_FEMALE)
            Score = CaculateScore(fatRate,FeMaleAgeBelow39fat,FatScore,sizeof(FatScore)/sizeof(uint16_t));
        else
            Score = CaculateScore(fatRate,MaleAgeBelow39fat,FatScore,sizeof(FatScore)/sizeof(uint16_t));
    }else if(age < 60){
        if(sex == D_SEX_FEMALE)
            Score = CaculateScore(fatRate,FeMaleAge40_59fat,FatScore,sizeof(FatScore)/sizeof(uint16_t));
        else
            Score = CaculateScore(fatRate,MaleAge40_59fat,FatScore,sizeof(FatScore)/sizeof(uint16_t));
    }else{
        if(sex == D_SEX_FEMALE)
            Score = CaculateScore(fatRate,FeMaleAgeOver60fat,FatScore,sizeof(FatScore)/sizeof(uint16_t));
        else
            Score = CaculateScore(fatRate,MaleAgeOver60fat,FatScore,sizeof(FatScore)/sizeof(uint16_t));     
    }
    return Score;
}

uint8_t CaculateBodyType(int8_t bmiScore,int8_t fatScore)
{
    uint8_t bmiIndex = 0;
    uint8_t FatIndex = 0;
    uint8_t BodyTypeIndex = 0;
    if(bmiScore < 0)
    {
        bmiScore = 0 - bmiScore;
        if(bmiScore < 40)
            bmiIndex = 0;
        else
            bmiIndex = 1;
    }else{
        if(bmiScore < 40)
            bmiIndex = 3;
        else if(bmiScore < 70)
            bmiIndex = 2;
        else 
            bmiIndex = 1;
    }
    if(fatScore < 0)
    {
        fatScore = 0 - fatScore;
        if(fatScore < 70)
            FatIndex = 0;
        else
            FatIndex = 1;
    }else{
        if(fatScore < 40)
            FatIndex = 3;
        else if(fatScore < 70)
            FatIndex = 2;
        else 
            FatIndex = 1;
    }
    switch(bmiIndex)
    {
        case    0:
                {
                    if(FatIndex <= 1)
                        BodyTypeIndex = 0;
                    else
                        BodyTypeIndex = 3;
                }
                break;
        case    1:
                {
                    if(FatIndex <= 1)
                        BodyTypeIndex = 1;
                    else
                        BodyTypeIndex = 3;
                }
                break;
        case    2:
        case    3:
                {
                    if(FatIndex <= 1)
                        BodyTypeIndex = 2;
                    else
                        BodyTypeIndex = 4;
                }
                break;
        default:
                BodyTypeIndex = 0;
                break;
    }
    return BodyTypeIndex;
}

uint8_t CaculateBodyScore(int8_t bmiScore,int8_t fatScore)
{
    if(bmiScore < 0)
        bmiScore = 0 - bmiScore;
    if(fatScore < 0)
        fatScore = 0 - fatScore;
    uint16_t bodyScore = bmiScore * 60;
    bodyScore += (fatScore * 40);
    return bodyScore/100;
}


void anlaysisTempScaleData(wisedaMijiaData_t *mcuDataT)
{
    uint8_t index = 0;
    if(WisedaCmd_Unlock == mcuDataT->cmd || WisedaCmd_Lock == mcuDataT->cmd)
    {
        ScaleWeightInfor.scaleType = mcuDataT->data[index++];
        ScaleWeightInfor.weight = mcuDataT->data[index++];
        ScaleWeightInfor.weight <<= 8;
        ScaleWeightInfor.weight += mcuDataT->data[index++];
        ScaleWeightInfor.PID = mcuDataT->data[index++];
        ScaleWeightInfor.PID <<= 8;
        ScaleWeightInfor.PID += mcuDataT->data[index++];
        ScaleWeightInfor.PID <<= 8;
        ScaleWeightInfor.PID += mcuDataT->data[index++];
        ScaleWeightInfor.PID <<= 8;
        ScaleWeightInfor.PID += mcuDataT->data[index++];
        ScaleWeightInfor.messageFlag += mcuDataT->data[index++];

        ScaleWeightInfor.impandance = mcuDataT->data[index++];
        ScaleWeightInfor.impandance <<= 8;
        ScaleWeightInfor.impandance += mcuDataT->data[index++];
    }

}

void anlaysisBodyCompise2Ble(wisedaMijiaData_t *mcuDataT)
{
    uint8_t index = 0;
    if(WisedaCmd_FinishData == mcuDataT->cmd)
    {
        userFinishData.utc = mcuDataT->data[index++];
        userFinishData.utc <<= 8;
        userFinishData.utc += mcuDataT->data[index++];
        userFinishData.utc <<= 8;
        userFinishData.utc += mcuDataT->data[index++];
        userFinishData.utc <<= 8;
        userFinishData.utc += mcuDataT->data[index++];
        userFinishData.messageFlag = mcuDataT->data[index++];
        userFinishData.ReseveFlag = mcuDataT->data[index++];
        memcpy((uint8_t *)&userFinishData.userID,&mcuDataT->data[index],4);
        index += 4;
        userFinishData.weightValue = mcuDataT->data[index++];
        userFinishData.weightValue <<= 8;
        userFinishData.weightValue += mcuDataT->data[index++];

        userFinishData.BodyFatRate = mcuDataT->data[index++];
        userFinishData.BodyFatRate <<= 8;
        userFinishData.BodyFatRate += mcuDataT->data[index++];

        userFinishData.BodyWaterRate = mcuDataT->data[index++];
        userFinishData.BodyWaterRate <<= 8;
        userFinishData.BodyWaterRate += mcuDataT->data[index++];

        userFinishData.BodyMucleWT = mcuDataT->data[index++];
        userFinishData.BodyMucleWT <<= 8;
        userFinishData.BodyMucleWT += mcuDataT->data[index++];

        userFinishData.BMR = mcuDataT->data[index++];
        userFinishData.BMR <<= 8;
        userFinishData.BMR += mcuDataT->data[index++];

        userFinishData.VFatLevle = mcuDataT->data[index++];
        userFinishData.VFatLevle <<= 8;
        userFinishData.VFatLevle += mcuDataT->data[index++];

        userFinishData.BodyProteinRate = mcuDataT->data[index++];
        userFinishData.BodyProteinRate <<= 8;
        userFinishData.BodyProteinRate += mcuDataT->data[index++];

        userFinishData.BodyBoneMucleWT = mcuDataT->data[index++];
        userFinishData.BodyBoneMucleWT <<= 8;
        userFinishData.BodyBoneMucleWT += mcuDataT->data[index++];

        userFinishData.BodyAge = mcuDataT->data[index++];

        userFinishData.BodyBoneWt = mcuDataT->data[index++];

        userFinishData.BMI = mcuDataT->data[index++];
        userFinishData.BMI <<= 8;
        userFinishData.BMI += mcuDataT->data[index++];

        userFinishData.standWeight = mcuDataT->data[index++];
        userFinishData.standWeight <<= 8;
        userFinishData.standWeight += mcuDataT->data[index++];    

        userFinishData.WeightContorl = mcuDataT->data[index++];
        userFinishData.WeightContorl <<= 8;
        userFinishData.WeightContorl += mcuDataT->data[index++];   

        userFinishData.MucleContorl = mcuDataT->data[index++];
        userFinishData.MucleContorl <<= 8;
        userFinishData.MucleContorl += mcuDataT->data[index++];  

        userFinishData.FatContorl = mcuDataT->data[index++];
        userFinishData.FatContorl <<= 8;
        userFinishData.FatContorl += mcuDataT->data[index++]; 

        userFinishData.FatWeight = mcuDataT->data[index++];
        userFinishData.FatWeight <<= 8;
        userFinishData.FatWeight += mcuDataT->data[index++]; 

        userFinishData.OutFatWeight = mcuDataT->data[index++];
        userFinishData.OutFatWeight <<= 8;
        userFinishData.OutFatWeight += mcuDataT->data[index++]; 

        userFinishData.BoneMucleRate = mcuDataT->data[index++];
        userFinishData.BoneMucleRate <<= 8;
        userFinishData.BoneMucleRate += mcuDataT->data[index++]; 
    
        userFinishData.BodyMucleRate = mcuDataT->data[index++];
        userFinishData.BodyMucleRate <<= 8;
        userFinishData.BodyMucleRate += mcuDataT->data[index++]; 

        userFinishData.BodyWaterWT = mcuDataT->data[index++];
        userFinishData.BodyWaterWT <<= 8;
        userFinishData.BodyWaterWT += mcuDataT->data[index++]; 

        userFinishData.BodyProteinWT = mcuDataT->data[index++];
        userFinishData.BodyProteinWT <<= 8;
        userFinishData.BodyProteinWT += mcuDataT->data[index++]; 

        userFinishData.BodyFatLeleve = mcuDataT->data[index++];
        userFinishData.BodyFatLeleve <<= 8;
        userFinishData.BodyFatLeleve += mcuDataT->data[index++]; 

        userFinishData.BodyType = mcuDataT->data[index++];
        userFinishData.BodyScore = mcuDataT->data[index++]; 
    }
}

/**
 * @brief 
 * @param  weightx          MyParamDoc
 * @param  MessageFlag      MyParamDoc
 * @return uint16_t         0.01kg
 */
uint16_t AnalayzeWeight2Kg(uint16_t weightx,uint8_t MessageFlag)  //输出固定为 2位小数 kg单位
{
    uint32_t weightKg = 0;
    uint8_t  DecPoint = 0;
    uint8_t  DecUint = 0;
    uint16_t uintMul = 1;
    uint16_t uintDiv = 1;
    DecPoint = (MessageFlag & 0x06)>>1;
    DecUint  = (MessageFlag & 0x18)>>3;

    if(DecPoint == 0x00)
        uintMul = 10;
    else if(DecPoint == 0x01)
        uintMul = 100;
    else
        uintMul = 1;
    switch(DecUint)
    {
        case    UINT_KG:
                weightKg = weightx * uintMul;
                break;
        case    UINT_JIN:
                uintDiv = 2;
                weightKg = weightx * uintMul/uintDiv;
                break;
        case    UINT_LB:
        case    UINT_STLB:
                weightKg = weightx * uintMul*10000;
                weightKg /= 22046;
                break;
        default:
                break;
    }
    return weightKg;
}

void CaculateMcuLeftCompsie2App(void)
{
    uint16_t   bodyweight = AnalayzeWeight2Kg(userFinishData.weightValue,userFinishData.messageFlag);
    userFinishData.BodyFatLeleve = CaculateFatLevle(bodyweight/10,userFinishData.standWeight);
    int8_t    bodyBmiScore = 0;
    int8_t    bodyFatScore = 0;
    if(userFinishData.BMI)
    {
        bodyBmiScore = CaculateBmiScore(userFinishData.BMI);
        if(userFinishData.BodyFatRate)
        {
            bodyFatScore = CaculateFatScore(userFinishData.BodyFatRate,userInfor.sex,userInfor.age);
            userFinishData.BodyType = CaculateBodyType(bodyBmiScore,bodyFatScore);
            userFinishData.BodyScore = CaculateBodyScore(bodyBmiScore,bodyFatScore);
            MI_LOG_INFO("bodyweight = %d\r\n",bodyweight);
            MI_LOG_INFO("bimScore = %d,fatScore = %d\r\n",bodyBmiScore,bodyFatScore);
        }
    }
}

uint32_t DividRound(int64_t DiV,int32_t Dived)
{
    uint8_t DivN = 0;
    uint8_t DivedN = 0; 
    if(DiV < 0)
    {
        DiV = 0 - DiV;
        DivN = 1;
    }
    if(Dived < 0)
    {
        Dived = 0 - Dived;
        DivedN = 1; 
    }
    DiV <<= 1;
    DiV /= Dived;
    DiV++;
    DiV >>= 1;
    if(DivN ^ DivedN)
        DiV = 0 - DiV;
    return DiV;
}
/**
 * @brief 
 * @param  userInfor        
 * @param  weight           0.01kg
 * @param  impandce         oum
 * @return uint16_t         0.1%
 */
uint16_t CaculateBodyFat(const UserInfor_t* const userInfor,uint16_t weight,uint16_t impandce)
{
    uint64_t tempData;
    uint64_t SubData;
    if(userInfor->sex == D_SEX_FEMALE)
    {
        tempData = 7509*weight;
        tempData += 19600 * userInfor->age;
        tempData += 7200 * impandce;
        tempData += 22719300;
        SubData = (333200*userInfor->height);
    }else{
        tempData = 6216*weight;
        tempData += 18300 * userInfor->age;
        tempData += 8500 * impandce;
        tempData += 22553900;
        SubData = (331500*userInfor->height);
    }
    if(tempData > SubData)
    {
        tempData -= SubData;
    }else{
        tempData = 0;
    }
    tempData /= weight;
    tempData = DividRound(tempData,10);
    if(tempData < 50)
        tempData = 50;
    if(tempData > 450)
        tempData = 450;
    return tempData;
}
/**
 * @brief 
 * @param  userInfor        
 * @param  weight           0.01kg
 * @param  impandce         oum
 * @return uint16_t         0.1kg
 */
uint16_t CaculateBodyMuscleWeight(const UserInfor_t* const userInfor,uint16_t weight,uint16_t impandce)
{
    uint64_t tempData;
    uint64_t SubData;
    uint16_t MuscleRate = 0;
    if(userInfor->sex == D_SEX_FEMALE)
    {
        tempData = 318600*userInfor->height;
        tempData += 1934 * weight;
        SubData = 20600*userInfor->age;
        SubData += 13200*impandce;
        SubData += 16455600;
    }else{
        tempData = 286700*userInfor->height;
        tempData += 3894 * weight;
        SubData = 40800*userInfor->age;
        SubData += 12400*impandce;
        SubData += 15766500;
    }
    if(tempData > SubData)
        tempData -= SubData;
    else
        tempData = 0;
    tempData = DividRound(tempData,100000);
    MuscleRate = Caculate2Persent(weight/10,tempData);
    if(MuscleRate > 950)
    {
        tempData = weight *95;
        tempData = DividRound(tempData,1000);
    }
    if(MuscleRate < 450)
    {
        tempData = weight *45;
        tempData = DividRound(tempData,1000);
    }
    if(tempData < 70)   //7.0kg
        tempData = 70;
    if(tempData > 1415)
        tempData = 1415;
    return tempData;
}

/**
 * @brief 
 * @param  weight           0.01kg
 * @param  FatPersent       0.1%
 * @return uint16_t         0.1kg
 */
uint16_t CaculateRate2Weight(uint16_t weight,uint16_t FatPersent)
{
    uint64_t tempData = weight * FatPersent;
    return DividRound(tempData,10000);
}

/**
 * @brief 
 * @param  weight           0.01kg
 * @param  FatWeight        0.01kg
 * @return uint16_t         0.1kg
 */
uint16_t CaculateBodyBoneWeight(uint16_t outFatweight,uint16_t MuscleWeight)
{
    int16_t bone = outFatweight - MuscleWeight;
    if(bone < 10)
        bone = 10;
    if(bone > 40)
        bone = 40;
    return bone;
}



/**
 * @brief 
 * @param  userInfor        
 * @param  weight           0.01kg
 * @param  impandce         oum
 * @return uint16_t         0.1%
 */
uint16_t CaculateBodyWater(const UserInfor_t* const userInfor,uint16_t weight,uint16_t impandce)
{
    uint64_t tempData;
    uint64_t SubData;
    if(userInfor->sex == D_SEX_FEMALE)
    {
        tempData = 87700*userInfor->height;
        tempData += 2973 * weight;
        tempData += 517500;
        tempData += 12800*userInfor->age;
        SubData = 6000*impandce;
    }else{
        tempData = 93900*userInfor->height;
        tempData += 3758 * weight;
        tempData += 97000;
        SubData = 3200*userInfor->age;
        SubData += 6900*impandce;
    }
    if(tempData > SubData)
        tempData -= SubData;
    else
        tempData = 0;
    tempData /= weight;
    tempData = DividRound(tempData,10);
    if(tempData < 200)
        tempData = 200;
    if(tempData > 850)
        tempData = 850;
    return tempData;
}

/**
 * @brief 
 * @param  weight           0.01kg
 * @param  MuscleWeight     0.1kg
 * @param  waterPersent     0.1%
 * 蛋白率低于5%时水分有调整
 * @return uint16_t 
 */
uint16_t CaculateBodyProtenPersent(uint16_t weight,uint16_t MuscleWeight,uint16_t waterPersent)
{
    uint64_t tempData;
    uint64_t SubData;
    SubData = weight * waterPersent;
    tempData = MuscleWeight*10000;
    tempData -= SubData;
    tempData = DividRound(tempData,weight);
    // if(tempData < 50)
    //     tempData = 50;
    // if(tempData > 320)
    //     tempData = 320;
    return tempData;
}

/**
 * @brief 
 * @param  userInfor        
 * @param  weight           0.01kg
 * @param  impandce         oum
 * @return uint16_t         0.1kg
 */
uint16_t CaculateBodyBoneMucaleWeight(const UserInfor_t* const userInfor,uint16_t weight,uint16_t impandce)
{
    uint64_t tempData;
    uint64_t SubData;
    if(userInfor->sex == D_SEX_FEMALE)
    {
        SubData = 20216500;
    }else{
        SubData = 17789600;
    }

    tempData = 257300*userInfor->height;
    tempData += 1745 * weight;
    SubData += 16100*userInfor->age;
    SubData += 17000*impandce;

    if(tempData > SubData)
        tempData -= SubData;
    else
        tempData = 0;
    tempData = DividRound(tempData,100000);
    // if(tempData < 450)
    //     tempData = 450;
    // else if(tempData > 700)
    //     tempData = 700;
    return tempData;
}

/**
 * @brief 
 * @param  Total            0.1kg
 * @param  part             0.1kg
 * @return uint16_t         0.1%
 */
uint16_t Caculate2Persent(uint16_t Total,uint16_t part)
{
    uint64_t tempData = part * 1000;
    return DividRound(tempData,Total);
}

/**
 * @brief 
 * @param  userInfor        
 * @param  weight           0.01kg
 * @param  impandce         oum
 * @return uint16_t         1Kcal
 */
uint16_t CaculateBodyBMR(const UserInfor_t* const userInfor,uint16_t weight,uint16_t impandce)
{
    uint64_t tempData;
    uint64_t SubData;
    if(userInfor->sex == D_SEX_FEMALE)
    {
        tempData = 7543200*userInfor->height;
        tempData += 99474 * weight;
        SubData = 3438200*userInfor->age;
        SubData += 309000*impandce;
        SubData += 288282100;
    }else{
        tempData = 7503700*userInfor->height;
        tempData += 131523 * weight;
        SubData = 4337600*userInfor->age;
        SubData += 348600*impandce;
        SubData += 311775100;
    }
    if(tempData > SubData)
        tempData -= SubData;
    else
        tempData = 0;

    tempData = DividRound(tempData,1000000);
    if(tempData < 400)
        tempData = 400;
    else if(tempData > 3500)
        tempData = 3500;
    return tempData;
}

/**
 * @brief 
 * @param  userInfor        
 * @param  weight           0.01kg
 * @param  impandce         oum
 * @return uint16_t         1Kcal
 */
uint16_t CaculateBodyVFR(const UserInfor_t* const userInfor,uint16_t weight,uint16_t impandce)
{
    uint64_t tempData;
    uint64_t SubData;
    if(userInfor->sex == D_SEX_FEMALE)
    {
        tempData = 64900*userInfor->age;
        tempData += 2628 * weight;
        tempData += 2400 * impandce;
        tempData += 12344500;
        SubData = 165100*userInfor->height;
    }else{
        tempData = 146200*userInfor->age;
        tempData += 4200 * weight;
        tempData += 12300 * impandce;
        tempData += 13987100;
        SubData = 267500*userInfor->height;
    }
    if(tempData > SubData)
        tempData -= SubData;
    else
        tempData = 0;
    tempData = DividRound(tempData,500000);
    tempData *= 5;
    if(tempData <= 10)
        tempData = 10;
    else if(tempData > 590)
        tempData = 590;
    return tempData;
}


/**
 * @brief 
 * @param  weight           0.01kg
 * @param  height           1cm
 * @return uint16_t         0.1 kg/m^2
 */
uint16_t CaculateBodyBMI(uint16_t weight,uint16_t height)
{
    uint64_t tempData = weight*1000;
    tempData /= height;
    return DividRound(tempData,height);
}


/**
 * @brief 
 * @param  height           1cm
 * @return uint16_t 
 */
uint16_t CaculateBodyDreamWeight(uint16_t height,uint8_t sex)
{
    // uint64_t tempData = height*height;
    // if(sex == D_SEX_FEMALE)
    // {
    //     tempData *= 20917;
    // }else{
    //     tempData *= 21564;
    // }
    // return DividRound(tempData,1000000);
    int64_t tempData = height;
    if(sex == D_SEX_FEMALE)
    {
        tempData -= 70;   
        if(tempData < 10)
            tempData = 10;     
        tempData *= 60;
    }else{
        tempData -= 80;
        if(tempData < 10)
            tempData = 10;
        tempData *= 70;
    }  
    return DividRound(tempData,10);
}

/**
 * @brief 
 * @param  weight           0.01Kg
 * @param  dreamWeight      0.1kg
 * @return uint16_t 
 */
int16_t CaculateBodyCtlWeight(uint16_t weight,uint16_t dreamWeight)
{
    int64_t tempData = dreamWeight * 10;
    tempData -= weight;
    return DividRound(tempData,10);
}

/**
 * @brief 
 * @param  Fatweight        0.1kg
 * @param  dreamWeight      0.1kg
 * @return uint16_t         0.1kg
 */
int16_t CaculateBodyCtlFat(uint16_t Fatweight,uint16_t dreamWeight,uint8_t sex)
{
    int64_t tempData;
    if(sex == D_SEX_FEMALE)
    {
        tempData = dreamWeight *25;
    }else{
        tempData = dreamWeight *17;
    }
    tempData -=  Fatweight*100;
    return DividRound(tempData,100);
}

// /**
//  * @brief 
//  * @param  weightCtl        0.1kg
//  * @param  fatCtl           0.1kg
//  * @return int16_t          0.1kg
//  */
// int16_t CaculateBodyCtlFat(int16_t weightCtl,uint16_t fatCtl)
// {
//     return weightCtl - fatCtl;
// }


/**
 * @brief 
 * @param  userInfor        
 * @param  weight           0.01kg
 * @param  impandce         oum
 * @return uint16_t         1age
 */
uint16_t CaculateBodyAge(const UserInfor_t* const userInfor,uint16_t weight,uint16_t impandce)
{
    uint64_t tempData;
    uint64_t SubData;
    if(userInfor->sex == D_SEX_FEMALE)
    {
        tempData = 15784 * weight;
        tempData += 461500 * userInfor->age;
        tempData += 41500 * impandce;
        tempData += 83254800;
        SubData = 1116500*userInfor->height;
    }else{
        tempData = 9161 * weight;
        tempData += 418400 * userInfor->age;
        tempData += 51700 * impandce;
        tempData += 54226700;
        SubData = 747100*userInfor->height;
    }
    if(tempData > SubData)
        tempData -= SubData;
    else
        tempData = 0;
    tempData = DividRound(tempData,1000000);
    if(tempData < 15)
        tempData = 15;
    else if(tempData > 80)
        tempData = 80;
    return tempData;
}

#define D_USER_HEIGHT_MIN   90           //90CM
#define D_USER_HEIGHT_MAX   220          //220CM
#define D_USER_WEIGHT_MIN   2000         //20kg
#define D_USER_WEIGHT_MAX   20000        //200kg
#define D_USER_AGE_MIN      18           //18Age
#define D_USER_AGE_MAX      99           //99Age
void CaculateBodyCompsie2App(const ScaleWeight_t* const weightInfor,const UserInfor_t* const userInfor)
{
    int8_t    bodyBmiScore = 0;
    int8_t    bodyFatScore = 0;
    uint16_t   bodyweight = AnalayzeWeight2Kg(weightInfor->weight,weightInfor->messageFlag);
    memset(&userFinishData,0,sizeof(userFinishData));
    userFinishData.utc = 0;
    userFinishData.messageFlag = weightInfor->messageFlag;
    userFinishData.ReseveFlag = 0;
    userFinishData.userID = 0;
    userFinishData.weightValue = weightInfor->weight;
    {
        if(userInfor->height < D_USER_HEIGHT_MIN || userInfor->height > D_USER_HEIGHT_MAX)
        {
            MI_LOG_INFO("height err:%d\r\n",userInfor->height);
            return;
        }
        if(bodyweight < D_USER_WEIGHT_MIN || bodyweight > D_USER_WEIGHT_MAX)
        {
            MI_LOG_INFO("weight err:%d\r\n",bodyweight);
            return;
        }
        if(userInfor->age < D_USER_AGE_MIN || userInfor->age > D_USER_AGE_MAX)
        {
            MI_LOG_INFO("age:%d\r\n",userInfor->age);
            return;
        }
    }
    userFinishData.BMI = CaculateBodyBMI(bodyweight,userInfor->height);
    if(weightInfor->impandance != 0xFFFF)       //fat ok
    {
        userFinishData.BodyFatRate = CaculateBodyFat(userInfor,bodyweight,weightInfor->impandance);
        userFinishData.BodyMucleWT = CaculateBodyMuscleWeight(userInfor,bodyweight,weightInfor->impandance);
        userFinishData.FatWeight = CaculateRate2Weight(bodyweight,userFinishData.BodyFatRate);
        userFinishData.OutFatWeight = bodyweight/10 - userFinishData.FatWeight;
        userFinishData.BodyBoneWt = CaculateBodyBoneWeight(userFinishData.OutFatWeight,userFinishData.BodyMucleWT);
        if(userFinishData.BodyBoneWt <= 10)
        {
            userFinishData.BodyBoneWt = 10;
            userFinishData.BodyMucleWT = userFinishData.OutFatWeight - 10;
        }else if(userFinishData.BodyBoneWt >= 40){
            userFinishData.BodyBoneWt = 40;
            userFinishData.BodyMucleWT = userFinishData.OutFatWeight - 40;
        }
        userFinishData.BodyWaterRate = CaculateBodyWater(userInfor,bodyweight,weightInfor->impandance);
        userFinishData.BodyProteinRate = CaculateBodyProtenPersent(bodyweight,userFinishData.BodyMucleWT,userFinishData.BodyWaterRate);
        if(userFinishData.BodyProteinRate <= 50)
        {
            userFinishData.BodyProteinRate = 50;
            userFinishData.BodyWaterRate = CaculateBodyProtenPersent(bodyweight,userFinishData.BodyMucleWT,userFinishData.BodyProteinRate);
        }else if(userFinishData.BodyProteinRate >= 320)
        {
            userFinishData.BodyProteinRate = 320;
            userFinishData.BodyWaterRate = CaculateBodyProtenPersent(bodyweight,userFinishData.BodyMucleWT,userFinishData.BodyProteinRate);
        }

        userFinishData.BodyBoneMucleWT = CaculateBodyBoneMucaleWeight(userInfor,bodyweight,weightInfor->impandance);
        userFinishData.BoneMucleRate = Caculate2Persent(userFinishData.BodyMucleWT,userFinishData.BodyBoneMucleWT);
        // userFinishData.BodyBoneMucleWT = CaculateRate2Weight(userFinishData.BodyBoneMucleWT*10,userFinishData.BoneMucleRate);
        userFinishData.BMR = CaculateBodyBMR(userInfor,bodyweight,weightInfor->impandance);
        userFinishData.VFatLevle = CaculateBodyVFR(userInfor,bodyweight,weightInfor->impandance);
        userFinishData.standWeight = CaculateBodyDreamWeight(userInfor->height,userInfor->sex);
        userFinishData.WeightContorl = CaculateBodyCtlWeight(bodyweight,userFinishData.standWeight);
        userFinishData.FatContorl = CaculateBodyCtlFat(userFinishData.FatWeight,userFinishData.standWeight,userInfor->sex);
        userFinishData.MucleContorl = userFinishData.WeightContorl - userFinishData.FatContorl;
        userFinishData.BodyAge = CaculateBodyAge(userInfor,bodyweight,weightInfor->impandance);
        userFinishData.BodyMucleRate = Caculate2Persent(bodyweight/10,userFinishData.BodyMucleWT);
        userFinishData.BodyWaterWT = CaculateRate2Weight(bodyweight,userFinishData.BodyWaterRate);
        userFinishData.BodyProteinWT = CaculateRate2Weight(bodyweight,userFinishData.BodyProteinRate);
        userFinishData.BodyFatLeleve = CaculateFatLevle(bodyweight/10,userFinishData.standWeight);

        bodyBmiScore = CaculateBmiScore(userFinishData.BMI);
        bodyFatScore = CaculateFatScore(userFinishData.BodyFatRate,userInfor->sex,userInfor->age);
        userFinishData.BodyType = CaculateBodyType(bodyBmiScore,bodyFatScore);
        userFinishData.BodyScore = CaculateBodyScore(bodyBmiScore,bodyFatScore);
        // MI_LOG_INFO("bodyweight = %d/100kg\r\n",bodyweight);
        // MI_LOG_INFO("bimScore = %d,fatScore = %d\r\n",bodyBmiScore,bodyFatScore);
        // MI_LOG_INFO("fatRate = %d/10%%\r\n",userFinishData.BodyFatRate);
        // MI_LOG_INFO("WaterRate = %d/10%%\r\n",userFinishData.BodyWaterRate);
        // MI_LOG_INFO("MucleRate = %d/10%%\r\n",userFinishData.BodyMucleRate);
        // MI_LOG_INFO("MucleWt = %d/10kg\r\n",userFinishData.BodyMucleWT);
        // MI_LOG_INFO("BMR = %d\r\n",userFinishData.BMR);
        // MI_LOG_INFO("VFR Lelve = %d\r\n",userFinishData.VFatLevle);
        // MI_LOG_INFO("ProteinRate = %d/10%%\r\n",userFinishData.BodyProteinRate);
        // MI_LOG_INFO("Bone MucleWeight = %d/10kg\r\n",userFinishData.BodyBoneMucleWT);
        // MI_LOG_INFO("bodyAge = %d\r\n",userFinishData.BodyAge);
        // MI_LOG_INFO("bone wt = %d/10kg\r\n",userFinishData.BodyBoneWt);
        // MI_LOG_INFO("BMI = %d/10kg\r\n",userFinishData.BMI);
        // MI_LOG_INFO("DreamWT = %d/10kg\r\n",userFinishData.standWeight);
        // MI_LOG_INFO("WeightCtl = %d/10kg\r\n",userFinishData.WeightContorl);
        // MI_LOG_INFO("MucleCtl = %d/10kg\r\n",userFinishData.MucleContorl);
        // MI_LOG_INFO("FatCtl = %d/10kg\r\n",userFinishData.FatContorl);
        // MI_LOG_INFO("Fat weight = %d/10kg\r\n",userFinishData.FatWeight);
        // MI_LOG_INFO("out Fat weight = %d/10kg\r\n",userFinishData.OutFatWeight);
        // MI_LOG_INFO("bone mucle rate = %d/10%%\r\n",userFinishData.BoneMucleRate);
        // MI_LOG_INFO("water weight = %d/10kg\r\n",userFinishData.BodyWaterWT);
        // MI_LOG_INFO("protein wt = %d/10kg\r\n",userFinishData.BodyProteinWT);
        // MI_LOG_INFO("body fat leve = %d/10%%\r\n",userFinishData.BodyFatLeleve);
        // MI_LOG_INFO("body type = %d\r\n",userFinishData.BodyType);
        // MI_LOG_INFO("body score = %d\r\n",userFinishData.BodyScore);
    }
}

// #include "user_process.h"
void PackBodyCompsie2App(wisedaMijiaData_t *pappData)
{
    uint8_t index = 0;
    pappData->Head = WISEDA_MIJIA_HEAD_STRE;
    pappData->Ver = WISEDA_MIJIA_VER;
    pappData->Length = 0x37;
    pappData->cmd = WisedaCmd_FinishData;
    pappData->data[index++] = (userFinishData.utc>>24)&0xFF; 
    pappData->data[index++] = (userFinishData.utc>>16)&0xFF; 
    pappData->data[index++] = (userFinishData.utc>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.utc)&0xFF; 
    pappData->data[index++] = (userFinishData.messageFlag)&0xFF; 
    pappData->data[index++] = (userFinishData.ReseveFlag)&0xFF; 
    pappData->data[index++] = (userFinishData.userID>>24)&0xFF; 
    pappData->data[index++] = (userFinishData.userID>>16)&0xFF; 
    pappData->data[index++] = (userFinishData.userID>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.userID)&0xFF; 
    pappData->data[index++] = (userFinishData.weightValue>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.weightValue)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyFatRate>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyFatRate)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyWaterRate>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyWaterRate)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyMucleWT>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyMucleWT)&0xFF; 
    pappData->data[index++] = (userFinishData.BMR>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.BMR)&0xFF; 
    pappData->data[index++] = (userFinishData.VFatLevle>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.VFatLevle)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyProteinRate>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyProteinRate)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyBoneMucleWT>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyBoneMucleWT)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyAge)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyBoneWt)&0xFF; 
    pappData->data[index++] = (userFinishData.BMI>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.BMI)&0xFF; 
    pappData->data[index++] = (userFinishData.standWeight>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.standWeight)&0xFF; 
    pappData->data[index++] = (userFinishData.WeightContorl>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.WeightContorl)&0xFF; 
    pappData->data[index++] = (userFinishData.MucleContorl>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.MucleContorl)&0xFF; 
    pappData->data[index++] = (userFinishData.FatContorl>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.FatContorl)&0xFF; 
    pappData->data[index++] = (userFinishData.FatWeight>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.FatWeight)&0xFF; 
    pappData->data[index++] = (userFinishData.OutFatWeight>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.OutFatWeight)&0xFF; 
    pappData->data[index++] = (userFinishData.BoneMucleRate>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.BoneMucleRate)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyMucleRate>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyMucleRate)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyWaterRate>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyWaterRate)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyProteinWT>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyProteinWT)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyFatLeleve>>8)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyFatLeleve)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyType)&0xFF; 
    pappData->data[index++] = (userFinishData.BodyScore)&0xFF;
    pappData->data[index++] = buff_xorCheck(&(pappData->Ver),pappData->Length+2);
}



